﻿namespace Yaaf.Wp7.AdvancedExplorer
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;

    using Microsoft.Devices;
    using Microsoft.Phone.Controls;
    using Microsoft.Phone.Shell;

    using Yaaf.Wp7.AdvancedExplorer.Resources;
    using Yaaf.Wp7.AdvancedExplorer.ViewModels;
    using Yaaf.WP7.NativeAccess.IO;
    using Yaaf.WP7.NativeAccess.Provision;
    using Yaaf.WP7.NativeAccess.Registry;

    using DirectoryInfo = Yaaf.WP7.NativeAccess.IO.DirectoryInfo;

    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            DataContext = App.ViewModel;

            if (!App.ViewModel.IsDataLoaded)
            {
                App.ViewModel.LoadData();
            }

            if (!translated)
            {
                // Translate App Menu
                AppMenuTranslatior.TranslateAppMenu(
                    (IApplicationBar)this.Resources["explorerApplicationBar"], AppResources.ResourceManager);
                AppMenuTranslatior.TranslateAppMenu(
                    (IApplicationBar)this.Resources["registryApplicationBar"], AppResources.ResourceManager);
                AppMenuTranslatior.TranslateAppMenu(
                    (IApplicationBar)this.Resources["settingsApplicationBar"], AppResources.ResourceManager);
                AppMenuTranslatior.TranslateAppMenu(
                    (IApplicationBar)this.Resources["remoteApplicationBar"], AppResources.ResourceManager);
                translated = true;
            }
        }

        private DoubleTabFix fix = new DoubleTabFix();

        private Clipboard clipboard;

        private bool translated = false;

        private void Vibrate()
        {
            VibrateController.Default.Start(TimeSpan.FromMilliseconds(50.0));
        }

        private void pivotElement_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

            var pivot = sender as Pivot;
            var item = pivot.SelectedItem as PivotItem;
            var dataContext = item.DataContext;
            if (dataContext != null)
            {
                var pivotView = (IPivotView)dataContext;
                var ressourceName = pivotView.Header + "ApplicationBar";
                this.ApplicationBar = (IApplicationBar)Resources[ressourceName];
                App.ViewModel.SwitchView(dataContext);
            }
        }

        private void PhoneApplicationPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (Settings.Current.ExitQuestion)
            {
                var result = MessageBox.Show(AppResources.MainpageExitQuestion, AppResources.MainpageExitQuestionTitle, MessageBoxButton.OKCancel);
                if (result == MessageBoxResult.Cancel)
                {
                    e.Cancel = true;
                }
            }
        }

        private void Input_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                this.Focus();
            }
        }

        #region FilePivot

        private void CreateFolderClick(object sender, EventArgs e)
        {
            var newDir = Path.Combine(App.ViewModel.ExplorerView.CurrentDirectory.FullName, AppResources.ExplorerNewFolder);
            var newElem = new WP7.NativeAccess.IO.DirectoryInfo(newDir);

            var model = new FileEntryViewModel(newElem);
            model.EditMode = true;
            App.ViewModel.ExplorerView.FileEntries.Insert(0, model);
        }

        private void ParentFolderClick(object sender, EventArgs e)
        {
            this.GoToParentFolder();
        }

        private void Grid_Loaded(object sender, RoutedEventArgs e)
        {
            var panel = sender as FrameworkElement;
            var gestures = GestureService.GetGestureListener(panel);
            gestures.Tap += new EventHandler<GestureEventArgs>(this.fileElement_Tap);
            gestures.DoubleTap += new EventHandler<GestureEventArgs>(this.fileElement_DoubleTap);
        }

        void fileElement_DoubleTap(object sender, GestureEventArgs e)
        {
            var panel = sender as FrameworkElement;
            var elem = panel.DataContext as FileEntryViewModel;
            var dir = elem.Element as Yaaf.WP7.NativeAccess.IO.DirectoryInfo;
            if (dir != null)
            {
                App.ViewModel.ExplorerView.CurrentDirectory = dir;
                return;
            }

            var file = elem.Element as WP7.NativeAccess.IO.FileInfo;
            if (file != null)
            {
                try
                {
                    ExtensionInformation.OpenFile(file);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(AppResources.CanNotOpenFile + ex.Message);
                }
            }
        }

        void fileElement_Tap(object sender, GestureEventArgs e)
        {
            if (fix.ShouldIgnoreTab(sender, e)) {return;}
            var panel = sender as FrameworkElement;
            var elem = panel.DataContext as FileEntryViewModel;
            elem.IsSelected = !elem.IsSelected;
        }

        void GoToParentFolder()
        {
            var current = App.ViewModel.ExplorerView.CurrentDirectory;
            var parent = current.Parent;
            if (parent != null)
            {
                App.ViewModel.ExplorerView.CurrentDirectory = parent;
            }
        }
        
        private void RefreshClick(object sender, EventArgs e)
        {
            App.ViewModel.ExplorerView.RefreshEntries();
        }

        private void EditClick(object sender, EventArgs e)
        {
            var selection = App.ViewModel.ExplorerView.FileEntries.Where(model => model.IsSelected);
            if (!selection.Any())
            {
                MessageBox.Show(AppResources.SelectAnItemFirst);
                return;
            }

            if (selection.ElementAtOrDefault(1) != null)
            {
                MessageBox.Show(AppResources.SelectOnlyOneItem);
                return;
            }

            var firstItem = selection.First();
            var file = firstItem.Element as WP7.NativeAccess.IO.FileInfo;
            if (file == null)
            {
                MessageBox.Show(AppResources.SelectAFile);
                return;
            }
            
            file.View();
        }

        private void FileCopySelectedClick(object sender, EventArgs e)
        {
            Vibrate();
            clipboard = new Clipboard(App.ViewModel.ExplorerView.FileEntries.Where(model => model.IsSelected).ToArray(), false);
        }

        private void FilePasteSelected(object sender, EventArgs e)
        {
            if (clipboard == null)
            {
                return;
            }

            var currentDir = App.ViewModel.ExplorerView.CurrentDirectory;
            if (clipboard.Files != null)
            {
                foreach (var fileEntryViewModel in clipboard.Files)
                {
                    try
                    {
                        if (clipboard.Cut)
                        {
                            fileEntryViewModel.Element.Move(currentDir, overwrite: true);
                        }
                        else
                        {
                            fileEntryViewModel.Element.CopyTo(currentDir, overwrite: false);
                        }

                        App.ViewModel.ExplorerView.FileEntries.Add(fileEntryViewModel);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(string.Format(AppResources.UnableToMoveOrCopyFile, ex));
                    }

                }
            }

            if (clipboard.RemoteFiles != null)
            {
                foreach (var remoteFiles in clipboard.RemoteFiles)
                {
                    try
                    {
                        remoteFiles.StartDownloadTo(currentDir);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(string.Format(AppResources.UnableToMoveOrCopyFile, ex));
                    }

                }
            }
        }

        private void FileDeleteSelectedClick(object sender, EventArgs e)
        {
            if (MessageBox.Show(AppResources.DeleteSelectedFiles, AppResources.DeleteSelectedFilesTitle, MessageBoxButton.OKCancel) == MessageBoxResult.Cancel)
            {
                return;
            }

            var removeList = new List<FileEntryViewModel>();
            foreach (var fileEntryViewModel in App.ViewModel.ExplorerView.FileEntries.Where(model => model.IsSelected))
            {
                bool exception = false;
                var dir = fileEntryViewModel.Element as WP7.NativeAccess.IO.DirectoryInfo;
                if (dir != null)
                {
                    try
                    {
                        dir.Delete(true);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(string.Format(AppResources.ErrorDeleteDirectory, ex.Message), AppResources.Error, MessageBoxButton.OK);
                        exception = true;
                    }
                }
                else
                {
                    try
                    {
                        fileEntryViewModel.Element.Delete();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(string.Format(AppResources.ErrorDeleteFile, ex.Message), AppResources.Error, MessageBoxButton.OK);
                        exception = true;
                    }
                }

                if (!exception)
                {
                    removeList.Add(fileEntryViewModel);
                }
            }

            foreach (var fileEntryViewModel in removeList)
            {
                App.ViewModel.ExplorerView.FileEntries.Remove(fileEntryViewModel);
            }
        }

        private void FileCutSelected(object sender, EventArgs e)
        {
            Vibrate();
            clipboard = new Clipboard(App.ViewModel.ExplorerView.FileEntries.Where(model => model.IsSelected).ToArray(), true);
        }

        private void FileRenameClick(object sender, EventArgs e)
        {
            foreach (var fileEntryViewModel in App.ViewModel.ExplorerView.FileEntries.Where(model => model.IsSelected))
            {
                fileEntryViewModel.EditMode = true;
            }
        }

        private void FileUpdateFileNameClick(object sender, RoutedEventArgs e)
        {
            var button = sender as Button;
            var box = button.DataContext as TextBox;
            var entry = box.DataContext as FileEntryViewModel;

            var dir = entry.Element as WP7.NativeAccess.IO.DirectoryInfo;

            entry.EditMode = false;

            FileSystemEntry newElem;
            try
            {
                bool createDir;
                try
                {
                    createDir = dir != null && !dir.Exists;
                }
                catch (Exception ex) 
                {
                    var t = App.ViewModel.ExplorerView.FileEntries.IndexOf(entry);
                    App.ViewModel.ExplorerView.FileEntries.RemoveAt(t);
                    throw;
                }

                if (createDir)
                {
                    if (string.IsNullOrEmpty(box.Text))
                    {
                        var i = App.ViewModel.ExplorerView.FileEntries.IndexOf(entry);
                        App.ViewModel.ExplorerView.FileEntries.RemoveAt(i);
                        return;
                    }
                    var newDir = Path.Combine(App.ViewModel.ExplorerView.CurrentDirectory.FullName, box.Text);
                    WP7.NativeAccess.IO.Directory.Create(newDir);
                    newElem = new WP7.NativeAccess.IO.DirectoryInfo(newDir);
                }
                else
                {
                    if (entry.ElementName != box.Text)
                    {
                        return;
                    }
                    else
                    {
                        newElem = entry.Element.Move(App.ViewModel.ExplorerView.CurrentDirectory, box.Text);
                    }
                }

                var index = App.ViewModel.ExplorerView.FileEntries.IndexOf(entry);
                App.ViewModel.ExplorerView.FileEntries.RemoveAt(index);
                App.ViewModel.ExplorerView.FileEntries.Insert(index, new FileEntryViewModel(newElem));
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format(AppResources.ErrorInvalidFileName, ex.Message));
            }
        }

        private void FileSendClick(object sender, EventArgs e)
        {
            foreach (var fileEntryViewModel in App.ViewModel.ExplorerView.FileEntries.Where(model => model.IsSelected))
            {
                fileEntryViewModel.Upload();
            }
        }

        private void FileSearchClick(object sender, EventArgs e)
        {
            App.ViewModel.IsFiltering = !App.ViewModel.IsFiltering;
            if (!App.ViewModel.IsFiltering)
            {
                App.ViewModel.CurrentFilter = null;
            }
        }

        private void ProvisionClick(object sender, EventArgs e)
        {
            try
            {
                foreach (var fileEntryViewModel in App.ViewModel.ExplorerView.FileEntries.Where(model => model.IsSelected))
                {
                    fileEntryViewModel.ProvisionIfPossible();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format(AppResources.ErrorProvisioning, ex));
            }
            
        }


        private void GoToFolderClick(object sender, EventArgs e)
        {
            var explorer = App.ViewModel.ExplorerView;

            var result = InputBoxHelper.ShowInputBox(
                AppResources.MainpageGotoFolderTitle, AppResources.MainpageGotoFolder, explorer.CurrentDirectoryFullName);
            if (result == null)
            {
                return;
            }

            var dir = new DirectoryInfo(result);
            explorer.CurrentDirectory = dir;
        }

        #endregion

        #region RegistryPivot

        private void GoToRegistryClick(object sender, EventArgs e)
        {
            var registry = App.ViewModel.RegistryView;

            var result = InputBoxHelper.ShowInputBox(
                AppResources.MainpageGotoRegistryTitle, AppResources.MainpageGotoRegistry, registry.CurrentRegistryKey.FullPath);
            if (result == null)
            {
                return;
            }

            registry.CurrentRegistryKey = new RegistryKey(result);
        }

        private void GridRegistry_Loaded(object sender, RoutedEventArgs e)
        {
            var panel = sender as FrameworkElement;
            var gestures = GestureService.GetGestureListener(panel);
            gestures.Tap += new EventHandler<GestureEventArgs>(this.registryElement_Tap);
            gestures.DoubleTap += new EventHandler<GestureEventArgs>(this.registryElement_DoubleTap);
        }

        void registryElement_DoubleTap(object sender, GestureEventArgs e)
        {
            var panel = sender as FrameworkElement;
            var elem = panel.DataContext as RegistryEntryViewModel;
            if (elem.Element != null)
            {
                App.ViewModel.RegistryView.CurrentRegistryKey = elem.Element;
            }
            else
            {
                this.GoToRegistryEditPage(elem.Value);
            }
        }


        private void GoToRegistryEditPage(RegistryValue value)
        {
            App.ViewModel.CurrentValueEditing = value;
            NavigationService.Navigate(new Uri("/SetRegistryKeyWindow.xaml", UriKind.Relative));
        }

        void registryElement_Tap(object sender, GestureEventArgs e)
        {
            if (fix.ShouldIgnoreTab(sender, e)) { return; }
            var panel = sender as FrameworkElement;
            var elem = panel.DataContext as RegistryEntryViewModel;
            elem.IsSelected = !elem.IsSelected;
        }

        private void RegistryGoUpClick(object sender, EventArgs e)
        {
            var registryView = App.ViewModel.RegistryView;
            var parent = registryView.CurrentRegistryKey.Parent;
            if (parent != null)
            {
                registryView.CurrentRegistryKey = registryView.CurrentRegistryKey.Parent;
            }
        }

        private void EditRegistryManualClick(object sender, EventArgs e)
        {
            this.GoToRegistryEditPage(new RegistryValue(App.ViewModel.RegistryView.CurrentRegistryKey.FullPath + "\\"));
        }

        private void RegistrySearchClick(object sender, EventArgs e)
        {
            App.ViewModel.IsFiltering = !App.ViewModel.IsFiltering;
        }

        #endregion

        #region SettingsPivot

        private void SaveSettingsClick(object sender, EventArgs e)
        {
            var settings = App.ViewModel.Settings;
            settings.Save();
            Settings.Current.SetAll(settings);
        }

        private void GoToInfoClick(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/InfoPage.xaml", UriKind.Relative));
        }
        #endregion

        #region RemotePivot
       

        private void SaveRemoteClick(object sender, EventArgs e)
        {
            this.Vibrate();
            clipboard = new Clipboard(App.ViewModel.RemoteConnection.FileEntries.Where(f => f.IsSelected).ToArray());
        }

        private void RefreshRemoteClick(object sender, EventArgs e)
        {
            App.ViewModel.RemoteConnection.Refresh();
        }

        private void RemoteGrid_Loaded(object sender, RoutedEventArgs e)
        {
            var panel = sender as FrameworkElement;
            var gestures = GestureService.GetGestureListener(panel);
            gestures.Tap += new EventHandler<GestureEventArgs>(this.remoteElement_Tap);
            gestures.DoubleTap += new EventHandler<GestureEventArgs>(this.remoteElement_DoubleTap);
        }

        void remoteElement_DoubleTap(object sender, GestureEventArgs e)
        {
            var panel = sender as FrameworkElement;
            var elem = panel.DataContext as RemoteFileEntryViewModel;
            if (!elem.Element.IsFile)
            {
                App.ViewModel.RemoteConnection.CurrentPath = App.ViewModel.RemoteConnection.CurrentPath + "\\" + elem.Element.Name;
                return;
            }
        }

        void remoteElement_Tap(object sender, GestureEventArgs e)
        {
            if (fix.ShouldIgnoreTab(sender, e)) { return; }
            var panel = sender as FrameworkElement;
            var elem = panel.DataContext as RemoteFileEntryViewModel;
            elem.IsSelected = !elem.IsSelected;
        } 
        
        private void ParentRemoteClick(object sender, EventArgs e)
        {
            var current = App.ViewModel.RemoteConnection.CurrentPath;
            if (string.IsNullOrEmpty(current))
            {
                return;
            }
            string newRoot;
            var index = current.LastIndexOf("\\");
            if (index < 0)
            {
                newRoot = "";
            }
            else
            {
                newRoot = current.Substring(0, index);
            }
            App.ViewModel.RemoteConnection.CurrentPath = newRoot.Trim('\\');

        }

        #endregion

       
    }

    internal class DoubleTabFix
    {
        public DoubleTabFix()
        {
        }

        private object lastSender;
        private DateTime lastTab = DateTime.Now - TimeSpan.FromMinutes(1);

        private object lastOriginalSource;

        public bool ShouldIgnoreTab(object sender, GestureEventArgs e)
        {
            bool ignore = false;
            var now = DateTime.Now;
            if ((now - lastTab) < TimeSpan.FromMilliseconds(100) && lastSender == sender && e.OriginalSource == lastOriginalSource)
            {
                ignore = true;
            }
            lastTab = now;
            lastOriginalSource = e.OriginalSource;
            lastSender = sender;
            return ignore;
        }
    }

    internal class Clipboard
    {
        private readonly FileEntryViewModel[] files;

        private readonly bool cut;

        private RemoteFileEntryViewModel[] remoteFiles;

        public Clipboard(FileEntryViewModel[] files, bool cut)
        {
            this.files = files;
            this.cut = cut;
        }

        public Clipboard(RemoteFileEntryViewModel[] remoteFiles)
        {
            this.remoteFiles = remoteFiles;
        }

        public RemoteFileEntryViewModel[] RemoteFiles
        {
            get
            {
                return this.remoteFiles;
            }
        }

        public FileEntryViewModel[] Files
        {
            get
            {
                return this.files;
            }
        }

        public bool Cut
        {
            get
            {
                return cut;
            }
        }
    }
}